/*
 * "Hello World" example.
 *
 * This example prints 'Hello from Nios II' to the STDOUT stream. It runs on
 * the Nios II 'standard', 'full_featured', 'fast', and 'low_cost' example
 * designs. It runs with or without the MicroC/OS-II RTOS and requires a STDOUT
 * device in your system's hardware.
 * The memory footprint of this hosted application is ~69 kbytes by default
 * using the standard reference design.
 *
 * For a reduced footprint version of this template, and an explanation of how
 * to reduce the memory footprint for a given application, see the
 * "small_hello_world" template.
 *
 */

#include <stdio.h>
#include <stdlib.h>
#include "LCD.h"
#include "sys/alt_alarm.h"
#include "alt_types.h"
#include "io.h"
#include "system.h"
#include "HAL4D13.h"
#include "isp_1362_regs.h"
#include <sys/alt_irq.h>
#include "chap9.h"
#include "common.h"
#include "usbBulk.h"
/////////////////////////////
alt_u32 my_alarm_callback (void* context);
void usb_device_irq(void * context,alt_u32 id);
 void usb_host_irq(void * context,alt_u32 id);
void usbInit(void);
////////////////////////////
void nullPrintf(const char *format,...)
{
return;
}
/////////--global variables///////////////////
int RTC_Time = 0;
int intr_count;
static alt_alarm alarm;
int intr,intr_temp;
alt_irq_context status;

usbEnuFsm usbEnuStatus;//enu fsm
USB_BULK_FSM bulkFsmStatus;//bulk fsm
int main()
{
    char dataBuf[256];

	int i;
	int dataLength;
    intr_count = 0;
  printf("Hello from Nios II!\n");
// LCD test
  LCD_Init();
  LCD_Show_Text("onerebos's");
  LCD_Line2();
  LCD_Show_Text("USB Mass storage");
// 
  LCD_Init();
  LCD_Show_Text("SJTU 2008");
  LCD_Line2();
  LCD_Show_Text("F0403023");
  //SEG7_DISPLAY_BASE
  
  if (alt_alarm_start (&alarm,
      alt_ticks_per_second(),
      my_alarm_callback,
      NULL) < 0)
   {
        printf ("No system clock available\n");
    }


  
	usb_1362_device_0_write(ISP_1362_DCReset_reg);//reset usb
   usbInit();
   intr = 0;
   while(1)
   {
    //usleep(100);
   if(intr == 1)
    {
    disable();
    uartprintf("intr: 0x%x\n",intr_temp);
	printf("intr: 0x%x\n",intr_temp);
	//uartprintf("intr: 0x%x\n",intr_temp);
	uartPrintf("intr: 0x%x\n",intr_temp);
        //alt_irq_disable(ISP1362_AVALON_SLAVE_1_IRQ);// enter the intr routine
        
        intr = 0;
  //      printf("intr:%08x\n",intr_temp);
       // printf("intr:%08x\n",usb_1362_device_32_read(ISP_1362_DcInterrupt_Read_reg));
       // printf("intr_count %08x\n",intr_count);
        /*EP0 OUT*/
        if(intr_temp & 0x100)
        {
        	if(usbEnuStatus.fsmStatus == USB_CONTROL_SETUP){
        	//disable();
            	usbEp0OutHandler(&usbEnuStatus); 
		//enable();
        		}
        }
	/* EP2 OUT*/
	   if(intr_temp & 0x800){
		//disable();
		printf("EP2 OUT status:%x\n",bulkFsmStatus. usbBulkEPOutStatus);
		usb_ep2_handler(&bulkFsmStatus);
		//enable();
		}
	/*EP1 IN*/
	   if(intr_temp &0x400){
		printf("EP1 IN\n");
		uartPrintf("EP1 IN\n");
		usb_ep1_handler(&bulkFsmStatus);
   		}
	  enable();
   	}
   }	

	
        
        //alt_irq_enable(ISP1362_AVALON_SLAVE_1_IRQ); 
    
    /*      intr_temp = usb_1362_device_32_read(ISP_1362_DcInterrupt_Read_reg);
        if( intr != intr_temp)
        {
            
            intr = intr_temp;
            printf("intr:%08x\n",intr);
        }
      */  
 

   while(1);
   return 0;
  
}

 alt_u32 my_alarm_callback (void* context)
 {
    RTC_Time++;
    char time[16];
    sprintf(time,"%d",RTC_Time);
    FILE* uart;
    uart = fopen(UART_0_NAME,"w");
    fprintf(uart,"Time->%d\n",RTC_Time);
    fclose(uart);
    LCD_Init();
    LCD_Show_Text(time);
    LCD_Line2();
    LCD_Show_Text("F0403023");
    
   /* This function will be called once/second */    
   return alt_ticks_per_second();
 }

 void usb_device_irq(void * context,alt_u32 id)
 {
 printf(".");
    disable();//alt_irq_disable(id);
	usb_1362_LockDevice(0xaa37);
    int i;
    int dataLength;
    intr = 1;
    intr_count++;
    char dataBuf[64];
    //usb_1362_device_16_wirte(0xb0,0xaa37);
    intr_temp = usb_1362_device_32_read(ISP_1362_DcInterrupt_Read_reg);
//#if USB_ENU_DEBUG
    uartPrintf("intr:%x\n",intr_temp);
    printf("intr:%x\n",intr_temp);  
//#endif
/*--EP0 OUT--*/
    if(intr_temp & 0x00100)
    {
//#if USB_ENU_DEBUG
    		printf("ep0 out intr\n");
//#endif
		usbEnuStatus.ep0Status = usb_1362_device_16_read(ISP_1362_DcEndpointStatus_EP0_OUT_Read_reg);

		if(usbEnuStatus.ep0Status & DcEndpointStatus_SETUPT_MSK)
			usbEnuStatus.fsmStatus = USB_CONTROL_SETUP;
		else if(usbEnuStatus.ep0Status & 0x60){
//#if USB_ENU_DEBUG
			printf("there is data in out fifo\n");
//#endif
			usb_1362_device_epx_read(0,usbEnuStatus.rxBuf);
			}
			
		
         //    printf("intr en:%08x\n",usb_1362_device_32_read(ISP_1362_DcInterrputEnable_Read_reg));
         //    printf("DcMode :%08x\n",usb_1362_device_16_read(ISP_1362_DcMode_Read_reg));   
   }
/*--EP0 IN--*/
	 if(intr_temp & 0x00200)
    {
  	  usb_1362_device_32_read(ISP_1362_DcInterrupt_Read_reg);
    	dataLength = usb_1362_device_16_read(ISP_1362_DcEndpointStatus_EP0_IN_Read_reg);
	printf("ep0 in status:%x\n",dataLength);
	printf("usb fsm status:%d\n",usbEnuStatus.fsmStatus);
#if USB_ENU_DEBUG
		printf("ep0 out status:%x\n",usb_1362_device_16_read(ISP_1362_DcEndpointStatus_EP0_OUT_Read_reg));
#endif
	if(usbEnuStatus.fsmStatus == USB_CONTROL_NONDATA){
		usb_1362_epx_transmit(0,0,0);	
        printf("in zero data**\n");
		printf("ep0 in intr\n");
		}
	else if(usbEnuStatus.fsmStatus ==  USB_CONTROL_SET ){
		printf("control set transmit 0\n");
		 usb_1362_epx_transmit(0,0,0);	
		 usbEnuStatus.fsmStatus = USB_CONTROL_IDLE;
		}
#if USB_ENU_DEBUG
    	printf("ep0 in intr\n");
#endif
		//alt_irq_enable(id); 
		
        //dataLength = usb_1362_device_epx_read(0,dataBuf);
    }
/*--EP2 OUT--*/
	 if(intr_temp & 0x800){
	 	printf("EP2 Intr...\n");
		// Get status
	 	bulkFsmStatus. usbBulkEPOutStatus= 
			usb_1362_device_16_read(ISP_1362_DcEndpointStatus_EPx_Read_reg(2));
#if USB_ENU_DEBUG
		printf("EP2 OUT status:%x\n",bulkFsmStatus. usbBulkEPOutStatus);
#endif
	 }
/*--EP1 IN--*/
	 if(intr_temp & 0x400){
	 	printf("EP1 Intr...\n");
		// Get status
	 	dataLength = 
			usb_1362_device_16_read(ISP_1362_DcEndpointStatus_EPx_Read_reg(1));
//#if USB_ENU_DEBUG
		printf("EP1 IN status:%x\n",dataLength);
//#endif
	 }

/* --RESET--*/
 	if(intr_temp & 0x0001){

		printf("reset!\n");
		uartPrintf("reset!\n");
		usbEnuStatus.fsmStatus = USB_CONTROL_IDLE;
		bulkFsmStatus.usbBulkFSMStatus = USB_BULK_IDLE;
		//usb_1362_disconnect();
		usleep(1);
		//USB_1362_connect();
 		}
/*--awake--*/
	 if(intr_temp & 0x0080){
//	 	printf("suspend -> awake!\n");
		//uartPrintf("suspend -> awake!\n");
		usbEnuStatus.fsmStatus = USB_CONTROL_IDLE;
		//usb_1362_disconnect();
		usleep(1);
		//USB_1362_connect();
	 	}
 //   for(i = 0;i < dataLength;i++)
 //       printf("0x%x\n",dataBuf[i]);

// 	printf("usb control status:%d\n",usbEnuStatus.fsmStatus);
//  	uartPrintf("usb control status:%d\n",usbEnuStatus.fsmStatus);

/**/	if((usbEnuStatus.fsmStatus == USB_CONTROL_SETUP))
		//	||
		//	(intr_temp&0x800))
 /**/		return;
/**/	else
			enable();//alt_irq_enable(id); 
 }
 
 void usb_host_irq(void * context,alt_u32 id)
 {
    printf("[nios] enter usb host intr\n");
 }

 void usbInit(void)//finish the fsm initializaion
 {

	short reg;
 /*--Enu FSM Init--*/
 	usbEnuStatus.rxBuf = malloc(64*sizeof(char));
 	usbEnuStatus.txBuf = malloc(64*sizeof(char));
	usbEnuStatus.fsmStatus = 0;
	usbEnuStatus.usbRequest = 0;
/*--Bulk FSM Init--*/
	bulkFsmStatus.usbBulkFSMStatus = USB_BULK_IDLE;
/*--UFI Data init--*/
	UFIDataInit();
/*--power usb chip--*/
	 IOWR_ISP_1362_PERIPHERAL_COMMAND(ISP1362_AVALON_SLAVE_0_BASE,ISP_1362_DCReset_reg);
  	//status=alt_irq_disable_all();
  	alt_irq_register(ISP1362_AVALON_SLAVE_1_IRQ,NULL,usb_device_irq);//irq 8
	alt_irq_register(ISP1362_AVALON_SLAVE_0_IRQ,NULL,usb_host_irq);//irq 7
   //alt_irq_enable_all(status);
    //status=alt_irq_disable_all();  
    	printf("chip ID : %04x\n",
      		usb_1362_device_16_read(ISP_1362_DcChipID_Read_reg));
   	printf("USB chip intr:%08x\n",\
      		usb_1362_device_32_read(ISP_1362_DcInterrupt_Read_reg));
   	usb_1362_device_32_write(ISP_1362_DcInterrputEnable_Write_reg,0x00000fcf);
   	usb_1362_device_16_write(ISP_1362_DcMode_Write_reg,1|(1<<3));
/*  */
	reg = usb_1362_device_16_read(ISP_1362_DcHardwareConfiguration_Read_reg);
	 usb_1362_device_16_write(ISP_1362_DcHardwareConfiguration_Write_reg,reg);
 }
 	
